package com.rfsp.common.shiro;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.session.SessionRepository;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 自定义SessionDAO，实现Shiro与Spring Session JDBC的集成
 */
@Component
public class SpringSessionDAO extends AbstractSessionDAO {

    @Autowired
    JdbcTemplate jdbcTemplate;

    static String host_key = "shiro_session_host";

    @Value("${spring.session.jdbc.table-name}")
    static String table_name;

    private final SessionRepository sessionRepository;

//    JdbcIndexedSessionRepository  jdbcIndexedSessionRepository;

    // 通过构造函数注入Spring Session的SessionRepository
    @Autowired
    public SpringSessionDAO(SessionRepository sessionRepository) {
        this.sessionRepository = sessionRepository;
    }

    @Override
    protected Serializable doCreate(Session session) {
        // 创建Spring Session
        org.springframework.session.Session springSession = sessionRepository.createSession();

        // 将Shiro Session的属性复制到Spring Session
        springSession = toSpringSession(session, springSession);

        // 保存Spring Session
        sessionRepository.save(springSession);

        // 设置Session ID
        Serializable sessionId = springSession.getId();
        assignSessionId(session, sessionId);

        return sessionId;
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
        if (sessionId == null) {
            return null;
        }

        // 从Spring Session仓库中获取会话
        org.springframework.session.Session springSession = sessionRepository.findById(sessionId.toString());
        if (springSession == null) {
            return null;
        }

        // 将Spring Session转换为Shiro Session
        return toShiroSession(springSession);
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
        if (session == null || session.getId() == null) {
            throw new UnknownSessionException("Session or session ID is null");
        }

        // 查找对应的Spring Session
        org.springframework.session.Session springSession = sessionRepository.findById(session.getId().toString());
        if (springSession == null) {
            throw new UnknownSessionException("Session with id " + session.getId() + " not found");
        }

        // 更新属性
        toSpringSession(session, springSession);

        // 保存更新
        sessionRepository.save(springSession);
    }

    @Override
    public void delete(Session session) {
        if (session == null || session.getId() == null) {
            return;
        }

        // 从Spring Session仓库中删除会话
        sessionRepository.deleteById(session.getId().toString());
    }

    @Override
    public Collection<Session> getActiveSessions() {
        // 注意：Spring Session JDBC不直接支持获取所有活跃会话
        // 这个方法需要根据实际需求实现，可能需要查询数据库  SESSION_ID   PRIMARY_ID
        List<String> ids = jdbcTemplate.queryForList("SELECT SESSION_ID FROM "+table_name, String.class);
        return ids.stream().map(this::doReadSession).collect(Collectors.toList());

//        return new HashSet<>();
    }

    /**
     * 将Shiro Session属性复制到Spring Session
     *
     * @return
     */
    private org.springframework.session.Session toSpringSession(Session fromSession, org.springframework.session.Session toSession) {
        fromSession.getAttributeKeys().forEach(key -> {
            Object value = fromSession.getAttribute(key);
            toSession.setAttribute(key.toString(), value);
        });
        toSession.setAttribute(host_key, fromSession.getHost());
        // 复制过期时间
        toSession.setMaxInactiveInterval(Duration.ofMillis(fromSession.getTimeout()));
        toSession.setLastAccessedTime(Instant.ofEpochMilli(System.currentTimeMillis()));
        return toSession;
    }

    /**
     * 将Spring Session转换为Shiro Session
     */
    private Session toShiroSession(org.springframework.session.Session springSession) {
        // 创建Shiro会话实例，这里使用SimpleSession作为示例
        SimpleSession shiroSession = new SimpleSession();

        // 设置会话ID
        shiroSession.setId(springSession.getId());

        // 设置创建时间和最后访问时间
        shiroSession.setStartTimestamp(Date.from(springSession.getCreationTime()));
        shiroSession.setLastAccessTime(Date.from(springSession.getLastAccessedTime()));

        // 设置超时时间
        shiroSession.setTimeout(springSession.getMaxInactiveInterval().toMillis());

        // 恢复host信息
        Object host = springSession.getAttribute(host_key);
        if (host instanceof String) {
            shiroSession.setHost((String) host);
        }
        // 复制属性
        springSession.getAttributeNames().forEach(attrName -> {
            shiroSession.setAttribute(attrName, springSession.getAttribute(attrName));
        });

        return shiroSession;
    }
}

